// TODO: headers 设置, 只要是 ua
use crate::component::request::{Method, Request, RequestBody};
use crate::component::response::Response;
use crate::component::Headers;
use ureq::Agent;

pub struct Downloader {
    client: Agent,
    /// 公共请求头
    headers: Headers,
}

impl Downloader {
    pub fn new() -> Self {
        Self {
            client: ureq::builder().user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0").build(),
            headers: Headers::new(vec![]),
        }
    }

    pub fn new_with_headers(headers: Headers) -> Self {
        Self {
            client: ureq::builder().user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0").build(),
            headers
        }
    }

    /// TODO: send json
    pub fn download<ItemType: Clone>(
        &self,
        req: Request<ItemType>,
    ) -> Result<Response<ItemType>, ureq::Error> {
        let req_ = req.clone();
        let Request {
            url,
            method,
            query,
            body,
            ..
        } = req_;

        // method
        let mut ureq_ = match method {
            Method::GET => self.client.get(url.as_str()),
            Method::POST => self.client.post(url.as_str()),
        };

        // 设置请求头
        // 先设置公共请求头
        for header in &self.headers.headers {
            ureq_ = ureq_.set(header.name(), header.value());
        }
        // 再设置本次请求头
        for header in &req_.headers.headers {
            ureq_ = ureq_.set(header.name(), header.value());
        }

        // 构建 query
        if let Some(query) = query {
            for (k, v) in query.iter() {
                ureq_ = ureq_.query(k, v);
            }
        }

        match body {
            RequestBody::Form(data) => {
                let data: Vec<(&str, &str)> = data.iter().map(|(k, v)| (&k[..], &v[..])).collect();
                match ureq_.send_form(&data) {
                    Ok(uresp) => Ok(Response::new(req, uresp)),
                    Err(e) => Err(e),
                }
            }
            RequestBody::Json(data) => match ureq_.send_json(data) {
                Ok(uresp) => Ok(Response::new(req, uresp)),
                Err(e) => Err(e),
            },
            RequestBody::Bytes(data) => match ureq_.send_bytes(data.as_slice()) {
                Ok(uresp) => Ok(Response::new(req, uresp)),
                Err(e) => Err(e),
            },
            RequestBody::Empty => match ureq_.call() {
                Ok(uresp) => Ok(Response::new(req, uresp)),
                Err(e) => Err(e),
            },
        }
    }
}
